From 79d2d0e40d35c2b22b4e9005486af6823b09c0e0 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 13 Nov 2016 16:16:39 +0100 Subject: [PATCH] snapshot: Add gtk_snapshot_render_background() and gtk_snapshot_render_frame() to be direct replacements for the old gtk_render_*() functions. Use them to replace Cairo usage completely in gtk_window_snapshot(). --- gtk/gtkrenderbackground.c | 43 +++++++++++++ gtk/gtkrenderbackgroundprivate.h | 7 ++- gtk/gtkrenderborder.c | 103 +++++++++++++++++++++++++++++++ gtk/gtkrenderborderprivate.h | 10 +++ gtk/gtksnapshot.c | 77 ++++++++++++++++++++++- gtk/gtksnapshot.h | 22 +++++++ gtk/gtkwindow.c | 74 ++++++++++------------ 7 files changed, 291 insertions(+), 45 deletions(-) diff --git a/gtk/gtkrenderbackground.c b/gtk/gtkrenderbackground.c index f3e09e480a..2e850ca271 100644 --- a/gtk/gtkrenderbackground.c +++ b/gtk/gtkrenderbackground.c @@ -593,3 +593,46 @@ gtk_css_style_render_background_is_opaque (GtkCssStyle *style) && corner_value_is_right_angle (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS)) && corner_value_is_right_angle (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS)); } + +void +gtk_css_style_snapshot_background (GtkCssStyle *style, + GtkSnapshot *snapshot, + gdouble width, + gdouble height, + GtkJunctionSides junction) +{ + GtkCssValue *background_image; + GtkCssValue *box_shadow; + const GdkRGBA *bg_color; + GtkBorder shadow; + graphene_rect_t bounds; + cairo_t *cr; + + background_image = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_IMAGE); + bg_color = _gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_COLOR)); + box_shadow = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BOX_SHADOW); + + /* This is the common default case of no background */ + if (gtk_rgba_is_clear (bg_color) && + _gtk_css_array_value_get_n_values (background_image) == 1 && + _gtk_css_image_value_get_image (_gtk_css_array_value_get_nth (background_image, 0)) == NULL && + _gtk_css_shadows_value_is_none (box_shadow)) + return; + + _gtk_css_shadows_value_get_extents (box_shadow, &shadow); + + graphene_rect_init (&bounds, + - shadow.left, + - shadow.top, + ceil (width) + shadow.left + shadow.right, + ceil (height) + shadow.top + shadow.bottom); + + cr = gtk_snapshot_append_cairo_node (snapshot, + &bounds, + "Background"); + + gtk_css_style_render_background (style, cr, 0, 0, width, height, junction); + + cairo_destroy (cr); +} + diff --git a/gtk/gtkrenderbackgroundprivate.h b/gtk/gtkrenderbackgroundprivate.h index a3927f087e..cb6ab5bc2f 100644 --- a/gtk/gtkrenderbackgroundprivate.h +++ b/gtk/gtkrenderbackgroundprivate.h @@ -24,8 +24,8 @@ #include #include "gtkcsstypesprivate.h" +#include "gtksnapshot.h" #include "gtktypes.h" -#include "gsk/gsk.h" G_BEGIN_DECLS @@ -47,6 +47,11 @@ void gtk_css_style_add_background_render_nodes (GtkCssStyle gdouble width, gdouble height, GtkJunctionSides junction); +void gtk_css_style_snapshot_background (GtkCssStyle *style, + GtkSnapshot *snapshot, + gdouble width, + gdouble height, + GtkJunctionSides junction); diff --git a/gtk/gtkrenderborder.c b/gtk/gtkrenderborder.c index f755f9f005..2672dec035 100644 --- a/gtk/gtkrenderborder.c +++ b/gtk/gtkrenderborder.c @@ -757,6 +757,71 @@ gtk_css_style_render_border (GtkCssStyle *style, } } +void +gtk_css_style_snapshot_border (GtkCssStyle *style, + GtkSnapshot *state, + gdouble width, + gdouble height, + GtkJunctionSides junction) +{ + GtkBorderImage border_image; + double border_width[4]; + graphene_rect_t bounds; + cairo_t *cr; + + border_width[0] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100); + border_width[1] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100); + border_width[2] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100); + border_width[3] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100); + + graphene_rect_init (&bounds, 0, 0, width, height); + + if (gtk_border_image_init (&border_image, style)) + { + cr = gtk_snapshot_append_cairo_node (state, + &bounds, + "Border Image"); + gtk_border_image_render (&border_image, border_width, cr, 0, 0, width, height); + cairo_destroy (cr); + } + else + { + GtkBorderStyle border_style[4]; + GtkRoundedBox border_box; + GdkRGBA colors[4]; + + /* Optimize the most common case of "This widget has no border" */ + if (border_width[0] == 0 && + border_width[1] == 0 && + border_width[2] == 0 && + border_width[3] == 0) + return; + + cr = gtk_snapshot_append_cairo_node (state, + &bounds, + "Border"); + + border_style[0] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_STYLE)); + border_style[1] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE)); + border_style[2] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE)); + border_style[3] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_STYLE)); + + hide_border_sides (border_width, border_style, 0); + + colors[0] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_COLOR)); + colors[1] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR)); + colors[2] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR)); + colors[3] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_COLOR)); + + _gtk_rounded_box_init_rect (&border_box, 0, 0, width, height); + _gtk_rounded_box_apply_border_radius_for_style (&border_box, style, junction); + + render_border (cr, &border_box, border_width, 0, colors, border_style); + + cairo_destroy (cr); + } +} + gboolean gtk_css_style_render_border_get_clip (GtkCssStyle *style, gdouble x, @@ -854,6 +919,44 @@ gtk_css_style_render_outline (GtkCssStyle *style, } } +void +gtk_css_style_snapshot_outline (GtkCssStyle *style, + GtkSnapshot *state, + gdouble width, + gdouble height) +{ + GtkBorderStyle border_style[4]; + GtkRoundedBox border_box; + double border_width[4]; + GdkRGBA colors[4]; + + border_style[0] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_STYLE)); + if (border_style[0] != GTK_BORDER_STYLE_NONE) + { + cairo_rectangle_t rect; + cairo_t *cr; + + compute_outline_rect (style, 0, 0, width, height, &rect); + + border_style[1] = border_style[2] = border_style[3] = border_style[0]; + border_width[0] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100); + border_width[3] = border_width[2] = border_width[1] = border_width[0]; + colors[0] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_COLOR)); + colors[3] = colors[2] = colors[1] = colors[0]; + + _gtk_rounded_box_init_rect (&border_box, rect.x, rect.y, rect.width, rect.height); + _gtk_rounded_box_apply_outline_radius_for_style (&border_box, style, GTK_JUNCTION_NONE); + + cr = gtk_snapshot_append_cairo_node (state, + &(graphene_rect_t) GRAPHENE_RECT_INIT (rect.x, rect.y, rect.width, rect.height), + "Outline"); + + render_border (cr, &border_box, border_width, 0, colors, border_style); + + cairo_destroy (cr); + } +} + gboolean gtk_css_style_render_outline_get_clip (GtkCssStyle *style, gdouble x, diff --git a/gtk/gtkrenderborderprivate.h b/gtk/gtkrenderborderprivate.h index b72010e985..e05a664c7d 100644 --- a/gtk/gtkrenderborderprivate.h +++ b/gtk/gtkrenderborderprivate.h @@ -25,6 +25,7 @@ #include "gtkborder.h" #include "gtkcssimageprivate.h" #include "gtkcssvalueprivate.h" +#include "gtksnapshot.h" G_BEGIN_DECLS @@ -43,6 +44,11 @@ gboolean gtk_css_style_render_border_get_clip (GtkCssStyle gdouble width, gdouble height, GdkRectangle *out_clip) G_GNUC_WARN_UNUSED_RESULT; +void gtk_css_style_snapshot_border (GtkCssStyle *style, + GtkSnapshot *state, + gdouble width, + gdouble height, + GtkJunctionSides junction); gboolean gtk_css_style_render_has_outline (GtkCssStyle *style); void gtk_css_style_render_outline (GtkCssStyle *style, @@ -51,6 +57,10 @@ void gtk_css_style_render_outline (GtkCssStyle gdouble y, gdouble width, gdouble height); +void gtk_css_style_snapshot_outline (GtkCssStyle *style, + GtkSnapshot *state, + gdouble width, + gdouble height); gboolean gtk_css_style_render_outline_get_clip (GtkCssStyle *style, gdouble x, gdouble y, diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c index c6382431b1..2a0507a338 100644 --- a/gtk/gtksnapshot.c +++ b/gtk/gtksnapshot.c @@ -20,6 +20,10 @@ #include "gtksnapshot.h" #include "gtksnapshotprivate.h" +#include "gtkrenderbackgroundprivate.h" +#include "gtkrenderborderprivate.h" +#include "gtkstylecontextprivate.h" + #include "gsk/gskrendernodeprivate.h" void @@ -45,8 +49,8 @@ gtk_snapshot_finish (GtkSnapshot *state) } void -gtk_snapshot_push (GtkSnapshot *state, - GskRenderNode *node) +gtk_snapshot_push_node (GtkSnapshot *state, + GskRenderNode *node) { gtk_snapshot_append_node (state, node); @@ -54,6 +58,35 @@ gtk_snapshot_push (GtkSnapshot *state, graphene_matrix_init_identity (&state->transform); } +void +gtk_snapshot_push (GtkSnapshot *state, + const graphene_rect_t *bounds, + const char *name, + ...) +{ + GskRenderNode *node; + + node = gsk_renderer_create_render_node (state->renderer); + gsk_render_node_set_bounds (node, bounds); + + if (name) + { + va_list args; + char *str; + + va_start (args, name); + str = g_strdup_vprintf (name, args); + va_end (args); + + gsk_render_node_set_name (node, str); + + g_free (str); + } + + gtk_snapshot_push_node (state, node); + gsk_render_node_unref (node); +} + void gtk_snapshot_pop (GtkSnapshot *state) { @@ -212,8 +245,46 @@ gtk_snapshot_push_cairo_node (GtkSnapshot *state, g_free (str); } - gtk_snapshot_push (state, node); + gtk_snapshot_push_node (state, node); gsk_render_node_unref (node); return gsk_render_node_get_draw_context (node, state->renderer); } + +void +gtk_snapshot_render_background (GtkSnapshot *state, + GtkStyleContext *context, + gdouble x, + gdouble y, + gdouble width, + gdouble height) +{ + g_return_if_fail (state != NULL); + g_return_if_fail (GTK_IS_STYLE_CONTEXT (context)); + + gtk_snapshot_translate_2d (state, x, y); + gtk_css_style_snapshot_background (gtk_style_context_lookup_style (context), + state, + width, height, + gtk_style_context_get_junction_sides (context)); + gtk_snapshot_translate_2d (state, -x, -y); +} + +void +gtk_snapshot_render_frame (GtkSnapshot *state, + GtkStyleContext *context, + gdouble x, + gdouble y, + gdouble width, + gdouble height) +{ + g_return_if_fail (state != NULL); + g_return_if_fail (GTK_IS_STYLE_CONTEXT (context)); + + gtk_snapshot_translate_2d (state, x, y); + gtk_css_style_snapshot_border (gtk_style_context_lookup_style (context), + state, + width, height, + gtk_style_context_get_junction_sides (context)); + gtk_snapshot_translate_2d (state, -x, -y); +} diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h index b5a4b38954..90ecef0d9e 100644 --- a/gtk/gtksnapshot.h +++ b/gtk/gtksnapshot.h @@ -32,6 +32,8 @@ #include +#include + G_BEGIN_DECLS typedef struct _GtkSnapshot GtkSnapshot; @@ -42,6 +44,11 @@ GskRenderer * gtk_snapshot_get_renderer (const GtkSnapshot GDK_AVAILABLE_IN_3_90 void gtk_snapshot_push (GtkSnapshot *state, + const graphene_rect_t *bounds, + const char *name, + ...) G_GNUC_PRINTF(3, 4); +GDK_AVAILABLE_IN_3_90 +void gtk_snapshot_push_node (GtkSnapshot *state, GskRenderNode *node); GDK_AVAILABLE_IN_3_90 cairo_t * gtk_snapshot_push_cairo_node (GtkSnapshot *state, @@ -71,6 +78,21 @@ cairo_t * gtk_snapshot_append_cairo_node (GtkSnapshot const char *name, ...) G_GNUC_PRINTF(3, 4); +GDK_AVAILABLE_IN_3_90 +void gtk_snapshot_render_background (GtkSnapshot *state, + GtkStyleContext *context, + gdouble x, + gdouble y, + gdouble width, + gdouble height); +GDK_AVAILABLE_IN_3_90 +void gtk_snapshot_render_frame (GtkSnapshot *state, + GtkStyleContext *context, + gdouble x, + gdouble y, + gdouble width, + gdouble height); + G_END_DECLS #endif /* __GTK_SNAPSHOT_H__ */ diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index c9522e744b..6232fcb1b0 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -9393,9 +9393,6 @@ gtk_window_snapshot (GtkWidget *widget, GtkBorder window_border; gint title_height; graphene_rect_t bounds; - graphene_matrix_t m; - graphene_point3d_t p; - cairo_t *cr; GList *l; context = gtk_widget_get_style_context (widget); @@ -9404,11 +9401,8 @@ gtk_window_snapshot (GtkWidget *widget, _gtk_widget_get_allocation (widget, &allocation); graphene_rect_init (&bounds, allocation.x, allocation.y, allocation.width, allocation.height); - graphene_matrix_init_translate (&m, graphene_point3d_init (&p, allocation.x, allocation.y, 0.)); - cr = gtk_snapshot_push_cairo_node (snapshot, - &bounds, - "Window Decoration"); + gtk_snapshot_push (snapshot, &bounds, "Window Decoration"); if (priv->client_decorated && priv->decorated && @@ -9425,28 +9419,28 @@ gtk_window_snapshot (GtkWidget *widget, gtk_style_context_get_border (context, &border); sum_borders (&border, &padding); - gtk_render_background (context, cr, - window_border.left - border.left, window_border.top - border.top, - allocation.width - - (window_border.left + window_border.right - border.left - border.right), - allocation.height - - (window_border.top + window_border.bottom - border.top - border.bottom)); - gtk_render_frame (context, cr, - window_border.left - border.left, window_border.top - border.top, - allocation.width - - (window_border.left + window_border.right - border.left - border.right), - allocation.height - - (window_border.top + window_border.bottom - border.top - border.bottom)); + gtk_snapshot_render_background (snapshot, context, + window_border.left - border.left, window_border.top - border.top, + allocation.width - + (window_border.left + window_border.right - border.left - border.right), + allocation.height - + (window_border.top + window_border.bottom - border.top - border.bottom)); + gtk_snapshot_render_frame (snapshot, context, + window_border.left - border.left, window_border.top - border.top, + allocation.width - + (window_border.left + window_border.right - border.left - border.right), + allocation.height - + (window_border.top + window_border.bottom - border.top - border.bottom)); } else { - gtk_render_background (context, cr, 0, 0, - allocation.width, - allocation.height); + gtk_snapshot_render_background (snapshot, context, 0, 0, + allocation.width, + allocation.height); - gtk_render_frame (context, cr, 0, 0, - allocation.width, - allocation.height); + gtk_snapshot_render_frame (snapshot, context, 0, 0, + allocation.width, + allocation.height); } gtk_style_context_restore (context); } @@ -9458,22 +9452,20 @@ gtk_window_snapshot (GtkWidget *widget, else title_height = 0; - gtk_render_background (context, cr, - window_border.left, - window_border.top + title_height, - allocation.width - - (window_border.left + window_border.right), - allocation.height - - (window_border.top + window_border.bottom + title_height)); - gtk_render_frame (context, cr, - window_border.left, - window_border.top + title_height, - allocation.width - - (window_border.left + window_border.right), - allocation.height - - (window_border.top + window_border.bottom + title_height)); - - cairo_destroy (cr); + gtk_snapshot_render_background (snapshot, context, + window_border.left, + window_border.top + title_height, + allocation.width - + (window_border.left + window_border.right), + allocation.height - + (window_border.top + window_border.bottom + title_height)); + gtk_snapshot_render_frame (snapshot, context, + window_border.left, + window_border.top + title_height, + allocation.width - + (window_border.left + window_border.right), + allocation.height - + (window_border.top + window_border.bottom + title_height)); if (priv->title_box != NULL) gtk_container_snapshot_child (GTK_CONTAINER (widget), priv->title_box, snapshot); -- 2.30.2